package cn.com.common.job.task;

import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.Duration;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import org.quartz.DisallowConcurrentExecution;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;

import cn.com.common.constants.Constants;
import cn.com.nr.entity.NrCaminfoForecastEntity;
import cn.com.gas.entity.GasStationinfoEntity;
import cn.com.gas.service.GasStationinfoService;
import cn.com.nr.entity.NrOfflineCamEntity;
import cn.com.nr.entity.NrRecordsEntity;
import cn.com.nr.entity.NrStationinfoForecastEntity;
import cn.com.nr.service.NrCaminfoForecastService;
import cn.com.nr.service.NrOfflineCamService;
import cn.com.nr.service.NrRecordsService;
import cn.com.nr.service.NrStationinfoForecastService;
import cn.com.util.TsBqUtils;

@Component("nrStationAndCamForecastProcessTask")
@DisallowConcurrentExecution
public class NrStationAndCamForecastProcessTask {

	@Value("${gasstation.timedTask.nrStationAndCamForecastProcessTask}")
	private String nrStationAndCamForecastProcessTask;

	private Logger logger = LoggerFactory.getLogger(getClass());

	@Autowired
	private GasStationinfoService stationinfoService;
	@Autowired
	private NrRecordsService nrRecordsService;
	@Autowired
	private NrStationinfoForecastService stationinfoForecastService;
	@Autowired
	private NrCaminfoForecastService caminfoForecastService;
	
	@Autowired
	private NrOfflineCamService offlineCamService;

	public void run(String params) throws Exception {
		logger.debug("nrStationAndCamForecastProcessTask定时任务正在执行，参数为：{}", params);
		logger.debug("application参数为nrStationAndCamForecastProcessTask：{}", nrStationAndCamForecastProcessTask);

		if (nrStationAndCamForecastProcessTask.equals(Constants.JOB_STOP)) {
			logger.debug("application配置文件控制不执行nrStationAndCamForecastProcessTask定时任务");
			throw new Exception("application配置文件控制不执行nrStationAndCamForecastProcessTask定时任务");
		}

		DateTimeFormatter _formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
		LocalDate yesterday = LocalDate.now().minusDays(1);
		LocalDateTime startOfYesterday = LocalDateTime.of(yesterday, LocalTime.MIN);
		LocalDateTime endOfYesterday = LocalDateTime.of(yesterday, LocalTime.MAX);

		String time = startOfYesterday.format(_formatter);

		if (TsBqUtils.isNotNull(params)) {
			
			String[] _paramsArr = params.split("_");
			
			for (String _params : _paramsArr) {
				
				DateTimeFormatter formatter1 = DateTimeFormatter.ofPattern("yyyyMMdd");
				LocalDate localDate = LocalDate.parse(_params, formatter1);
				startOfYesterday = LocalDateTime.of(localDate, LocalTime.MIN);
				endOfYesterday = LocalDateTime.of(localDate, LocalTime.MAX);
				time = localDate.format(_formatter);
				
				logger.debug("nrStationAndCamForecastProcessTask定时任务正在执行，加工日期：{}", _params);
				handleData(startOfYesterday, endOfYesterday, time, _formatter);
				logger.debug("nrStationAndCamForecastProcessTask定时任务正在执行，加工完成：{}", _params);

			}

		} else {
			logger.debug("nrStationAndCamForecastProcessTask定时任务正在执行，加工日期：{}", time);
			handleData(startOfYesterday, endOfYesterday, time, _formatter);
			logger.debug("nrStationAndCamForecastProcessTask定时任务正在执行，加工完成：{}", time);

		}

	}

	// 处理数据
	private String handleData(LocalDateTime startOfYesterday, LocalDateTime endOfYesterday, String time,
			DateTimeFormatter _formatter) throws ParseException {
		Date date = new Date();
		
		SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 
		// DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

		// String startDateStr = startOfYesterday.format(formatter);
		// String endDateStr = endOfYesterday.format(formatter);
		
		// Date[] startOfYesterdayArr = { format.parse(startDateStr) };
		// Date[] endOfYesterdayArr = { format.parse(endDateStr) };
		
		// 计算离线率
		LambdaQueryWrapper<NrOfflineCamEntity> queryOfflineCam = Wrappers.lambdaQuery();
		queryOfflineCam.ge(NrOfflineCamEntity::getOfflineTime, localDateTimeToDate(startOfYesterday));
		queryOfflineCam.le(NrOfflineCamEntity::getOfflineTime, localDateTimeToDate(endOfYesterday));
		List<NrOfflineCamEntity> offlineCamList = offlineCamService.list(queryOfflineCam);
		List<NrOfflineCamEntity> TimePeriodList = new ArrayList<NrOfflineCamEntity>();

		for (NrOfflineCamEntity offlineCam : offlineCamList) {

			String offlineTime = offlineCam.getOfflineTime();
			
			String recoverTime = offlineCam.getRecoverTime();
			
			try {
				Date offlineTimeDate = format.parse(offlineTime);

				if (TsBqUtils.isNull(recoverTime)) {
					// 恢复时间为空的情况
					recoverTime = startOfYesterday.format(_formatter) + " 23:59:59";
				} else {
					// 恢复时间不为空的情况
					Date recoverTimeDate = format.parse(recoverTime);
					if (endOfYesterday.isBefore(dateToLocalDateTime(recoverTimeDate))) {
						recoverTime = startOfYesterday.format(_formatter) + " 23:59:59";
					}
				}
				
				if (dateToLocalDateTime(offlineTimeDate).isBefore(startOfYesterday)) {
					offlineTime = startOfYesterday.format(_formatter) + " 00:00:01";
				}
				
				Duration duration = Duration.between(dateToLocalDateTime(format.parse(offlineTime)),
						dateToLocalDateTime(format.parse(recoverTime)));

				long minutes = duration.toMillis() / 1000; // 相差秒数

				offlineCam.setTimePeriod(String.valueOf(minutes));
				TimePeriodList.add(offlineCam);

			} catch (ParseException e) {
				logger.error(e.getMessage() + "====offlineCam====" + offlineCam.getId());
				e.printStackTrace();
			}

		}

		List<NrOfflineCamEntity> offlineCamGroup = new ArrayList<NrOfflineCamEntity>();
		if (TsBqUtils.isNotNull(TimePeriodList)) {

			Map<String, List<NrOfflineCamEntity>> groupedItems = TimePeriodList.stream()
					.collect(Collectors.groupingBy(item -> item.getCamId()));
			groupedItems.forEach((category, itemsInCategory) -> {
				if (TsBqUtils.isNotNull(category)) {
					BigDecimal[] timePeriod = { new BigDecimal(0) };
					itemsInCategory.forEach(item -> {
						timePeriod[0] = timePeriod[0].add(new BigDecimal(item.getTimePeriod()));
					});

					NrOfflineCamEntity offlineCam = new NrOfflineCamEntity();
					offlineCam.setCamId(category);

					offlineCam.setTimePeriod(timePeriod[0].toString());

					offlineCamGroup.add(offlineCam);

				}
			});

		}

		// 计算时间情况
		LambdaQueryWrapper<NrRecordsEntity> queryStaytimeResult = Wrappers.lambdaQuery();
        Date startOfYesterdayDate = Date.from(startOfYesterday.atZone(ZoneId.systemDefault()).toInstant());
        Date endOfYesterdayDate = Date.from(endOfYesterday.atZone(ZoneId.systemDefault()).toInstant());

		queryStaytimeResult.ge(NrRecordsEntity::getTime, startOfYesterdayDate);
		queryStaytimeResult.le(NrRecordsEntity::getTime, endOfYesterdayDate);
		List<NrRecordsEntity> nrRecordsList = nrRecordsService.list(queryStaytimeResult);

		List<NrRecordsEntity> camidAndCalculateList = new ArrayList<>();
		// 处理摄像头ID
		for (NrRecordsEntity nrRecordsEntity : nrRecordsList) {

			String camid = nrRecordsEntity.getMessageCamid();
			String calculate = nrRecordsEntity.getCalculate();

			if (TsBqUtils.isNotNull(camid)) {

				NrRecordsEntity entity = new NrRecordsEntity();
				entity.setCalculate(calculate);
				entity.setMessageCamid(camid);

				camidAndCalculateList.add(entity);
			}
		}

		List<NrRecordsEntity> calculateCamGroup = new ArrayList<NrRecordsEntity>();

		if (TsBqUtils.isNotNull(camidAndCalculateList)) {
			// 按照摄像头分组
			Map<String, List<NrRecordsEntity>> groupedItems = camidAndCalculateList.stream()
					.collect(Collectors.groupingBy(item -> item.getMessageCamid()));

			groupedItems.forEach((category, itemsInCategory) -> {
				if (TsBqUtils.isNotNull(category)) {
					BigDecimal[] calculate = { new BigDecimal(0) };
					itemsInCategory.forEach(item -> {
						String[] tmp = {"0"};
						if(TsBqUtils.isNotNull(item.getCalculate())){
							tmp[0] = item.getCalculate();
						}
						calculate[0] = calculate[0].add(new BigDecimal(tmp[0]));
					});

					NrRecordsEntity entity = new NrRecordsEntity();
					entity.setMessageCamid(category);
					entity.setCalculate(calculate[0].toString());
					String amount = itemsInCategory.size() + "";
					entity.setAmount(amount);
					calculateCamGroup.add(entity);
					
				}
			});
		}

		List<NrCaminfoForecastEntity> caminfoForecastList = new ArrayList<>();

		if (TsBqUtils.isNotNull(calculateCamGroup)) {
			
			for (NrRecordsEntity priceCam : calculateCamGroup) {
				// 吨数 和 车次
				String calculat = priceCam.getCalculate();
				String amount = priceCam.getAmount();
				
				String camid = priceCam.getMessageCamid();
				
				String timePeriod = "0";
				for (NrOfflineCamEntity offlineCam : offlineCamGroup) {
					String camId = offlineCam.getCamId();
					if (camid.equals(camId)) {
						timePeriod = offlineCam.getTimePeriod();
					}
				}

				NrCaminfoForecastEntity caminfoForecast = new NrCaminfoForecastEntity();
				GasStationinfoEntity gasStationinfo = stationinfoService.getById(camid);
				if (TsBqUtils.isNotNull(gasStationinfo)) {

					caminfoForecast.setTime(time);
					caminfoForecast.setStationinfoId(gasStationinfo.getPid());
					caminfoForecast.setCamId(gasStationinfo.getId());
					// caminfoForecast.setTaxorgcode();
					
					caminfoForecast.setGatherValue(amount);
					caminfoForecast.setGatherCalculat(calculat);
					
					BigDecimal _amount = new BigDecimal(amount);
					BigDecimal _calculat = new BigDecimal(calculat);

					if (TsBqUtils.isNull(timePeriod) || "0".equals(timePeriod)) {
						caminfoForecast.setForecastValue(amount);
						caminfoForecast.setForecastCalculat(calculat);
						
					} else {
						
						BigDecimal bigDecimal = new BigDecimal("86400");
						BigDecimal subtract = bigDecimal.subtract(new BigDecimal(timePeriod));
						// 计算吨数预估
						BigDecimal _calculatDivide = _calculat.multiply(bigDecimal);
						BigDecimal _calculatMultiply = _calculatDivide.divide(subtract, 2, BigDecimal.ROUND_HALF_UP);
						caminfoForecast.setForecastCalculat(_calculatMultiply.toString());
						// 计算车次预估
						BigDecimal _amountDivide = _amount.multiply(bigDecimal);
						BigDecimal _amountMultiply = _amountDivide.divide(subtract, 2, BigDecimal.ROUND_HALF_UP);
						caminfoForecast.setForecastValue(_amountMultiply.toString());
						
					}

					caminfoForecast.setOfflineTime(timePeriod);
					caminfoForecast.setDeleted(Constants.DELETEED_NOT);
					caminfoForecast.setCreateId("job");
					caminfoForecast.setCreateTime(date);
					caminfoForecastList.add(caminfoForecast);

				} else {
					logger.debug("gasStationAndCamForecastProcessTask定时任务正在执行，gasStationinfo未查询到camid:" + camid);
				}

			}
		}

		// 保存到 gas_caminfo_forecast
		if (TsBqUtils.isNotNull(caminfoForecastList)) {
			for (NrCaminfoForecastEntity caminfoForecast : caminfoForecastList) {
				caminfoForecastService.realDelete(caminfoForecast);
				caminfoForecastService.save(caminfoForecast);
			}

			List<NrStationinfoForecastEntity> stationinfoForecastList = new ArrayList<>();

			// 保存到 gas_stationinfo_forecast
			Map<String, List<NrCaminfoForecastEntity>> groupedItems = caminfoForecastList.stream()
					.collect(Collectors.groupingBy(item -> item.getStationinfoId() + "_" + item.getTime()));

			groupedItems.forEach((category, itemsInCategory) -> {
				if (TsBqUtils.isNotNull(category)) {
					String[] arr = category.split("_");

					String stationinfoId = arr[0];
					String _time = arr[1];

					BigDecimal[] forecastValue = { new BigDecimal(0) };
					BigDecimal[] gatherValue = { new BigDecimal(0) };
					
					BigDecimal[] forecastCalculat = { new BigDecimal(0) };
					BigDecimal[] gatherCalculat = { new BigDecimal(0) };
					
					itemsInCategory.forEach(item -> {
						forecastValue[0] = forecastValue[0].add(new BigDecimal(item.getForecastValue())); // 预估值
						gatherValue[0] = gatherValue[0].add(new BigDecimal(item.getGatherValue())); // 采集值
						
						forecastCalculat[0] = forecastCalculat[0].add(new BigDecimal(item.getForecastCalculat())); // 预估值
						gatherCalculat[0] = gatherCalculat[0].add(new BigDecimal(item.getGatherCalculat())); // 采集值
						
					});

					NrStationinfoForecastEntity stationinfoForecast = new NrStationinfoForecastEntity();
					GasStationinfoEntity stationinfo = stationinfoService.getById(stationinfoId);

					stationinfoForecast.setTime(_time);

					stationinfoForecast.setStationinfoId(stationinfoId);
					stationinfoForecast.setTaxorgcode(stationinfo.getTaxorgcode());

					stationinfoForecast.setGatherValue(gatherValue[0].toString());
					stationinfoForecast.setForecastValue(forecastValue[0].toString());

					stationinfoForecast.setGatherCalculat(gatherCalculat[0].toString());
					stationinfoForecast.setForecastCalculat(forecastCalculat[0].toString());
					

					stationinfoForecast.setDeleted(Constants.DELETEED_NOT);
					stationinfoForecast.setCreateId("job");
					stationinfoForecast.setCreateTime(date);

					stationinfoForecastList.add(stationinfoForecast);

				}
			});

			if (TsBqUtils.isNotNull(stationinfoForecastList)) {

				for (NrStationinfoForecastEntity stationinfoForecast : stationinfoForecastList) {
					// 删除数据
					stationinfoForecastService.realDelete(stationinfoForecast);
					stationinfoForecastService.save(stationinfoForecast);
				}
			}

		}
		return null;
	}

	private static LocalDateTime dateToLocalDateTime(Date date) {
		Instant instant = date.toInstant();
		return LocalDateTime.ofInstant(instant, ZoneId.systemDefault());

	}
	
	private static Date localDateTimeToDate(LocalDateTime localDateTime) {
		ZoneId zoneId = ZoneId.systemDefault();
		ZonedDateTime zdt = localDateTime.atZone(zoneId);
		return Date.from(zdt.toInstant());
	}
	  
	
}
